home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 08 - 1992 / 08.03 Jul 92 / Equation Compiler / Demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-17  |  6.0 KB  |  226 lines  |  [TEXT/KAHL]

  1. /* Code for demo program */
  2.  
  3. #include    <SANE.h>
  4. #include    "Demo.h"
  5. #include    "EqnCompiler.h"
  6.  
  7. /* Global Variables */
  8. Handle        eqnCode;                    /* handle to block of code */
  9. char            **eqnText;                /* handle to eqn text */
  10. extended        (*eqnFn)();                /* func ptr to eqn code */
  11. extended        coeff[5];                    /* array of coefficients */
  12. extended        minX, maxX, minY, maxY;        /* plot range */
  13. DialogPtr        eqnDialog;                    /* dialog pointer */
  14. CursHandle    iBeam, watch;
  15.  
  16. main()
  17. {
  18.     Handle    userItemH;
  19.     int        i, type, itemHit, error, index;
  20.     Rect        rect;
  21.     
  22.     InitStuff();
  23.     eqnDialog = GetNewDialog(300, NULL, (WindowPtr) -1); /* get dialog */
  24.     GetDItem(eqnDialog, FUNCTION, &type, &eqnText, &rect); /* get handle to eqn text */
  25.     GetDItem(eqnDialog, FRAME, &type, &userItemH, &rect); /* get user item (plot frame) */
  26.     SetDItem(eqnDialog, FRAME, type, FramePlot, &rect); /* install user item */
  27.     /* centre window on screen */
  28.     MoveWindow(eqnDialog, (screenBits.bounds.right-screenBits.bounds.left - 490)/2, 45, true);
  29.     ShowWindow(eqnDialog);
  30.     SetPort(eqnDialog);
  31.     
  32.     do {
  33.         ModalDialog(DialogFilter, &itemHit);
  34.         if (itemHit == COMPILE) { /* compile eqn */
  35.             /* Code block should be unlocked and */
  36.             /* eqn text buffer should be locked. */
  37.             HUnlock(eqnCode);
  38.             HLock(eqnText);
  39.             index = 0; /* parse text from start */
  40.             error = CompileEqn(*eqnText, GetHandleSize(eqnText), &index, eqnCode);
  41.             if (error) {
  42.                 /* position of error is in index */
  43.                 SelIText (eqnDialog, FUNCTION, index, index);
  44.                 /* put up alert to explain error */
  45.                 SyntaxErr(error);
  46.                 eqnFn = NULL; /* null function ptr */
  47.             } else {
  48.                 SelIText (eqnDialog, FUNCTION, 0, 0);
  49.                 /* compiled OK, lock code block and */
  50.                 /* dereference to get address of func */
  51.                 HLock(eqnCode);
  52.                 eqnFn = (void *) *eqnCode;
  53.             }
  54.         } else if (itemHit == PLOT) { /* plot eqn */
  55.             /* update coefficients array */
  56.             for (i=0; i<5; i++)
  57.                 coeff[i] = GetEditField(COEFF_A + i);
  58.             /* update plot range */
  59.             minX = GetEditField(MIN_X);
  60.             maxX = GetEditField(MAX_X);
  61.             minY = GetEditField(MIN_Y);
  62.             maxY = GetEditField(MAX_Y);
  63.             PlotEqn();
  64.         }
  65.     } while (itemHit != QUIT);
  66.     
  67.     DisposDialog(eqnDialog); /* tidy up & leave */
  68.     HUnlock(eqnCode);
  69. }
  70.  
  71. void    InitStuff(void)
  72. {
  73.     MaxApplZone();
  74.     InitGraf(&thePort);
  75.     InitFonts();
  76.     FlushEvents(everyEvent, 0);
  77.     InitWindows();
  78.     TEInit();
  79.     InitDialogs(NULL);
  80.     
  81.     eqnCode = NewHandle(0); /* allocate memory */
  82.     if (MemError()) ExitToShell();
  83.     eqnFn = NULL;
  84.     iBeam = GetCursor(iBeamCursor);
  85.     watch = GetCursor(watchCursor);
  86.     InitCursor();
  87. }
  88.  
  89. /* Plot the equation */
  90. void    PlotEqn(void)
  91. {
  92.     extended    x, y, vert;
  93.     int        hPos=0, lastvPos, vPos;
  94.     char        skip=2;
  95.     Rect        plotRect, bigRect;
  96.     
  97.     if (!eqnFn) return; /* invalid function */
  98.     if ((minX >= maxX) || (minY >= maxY))
  99.         return; /* invalid plot range */
  100.     SetRect(&plotRect, 170, 59, 470, 230);
  101.     EraseRect(&plotRect); /* clear plot area */
  102.     ClipRect(&plotRect); /* new clip region */
  103.     SetCursor(*watch);
  104.     
  105.     do {
  106.         /* calculate x */
  107.         x = minX + (maxX - minX)*hPos/300.0;
  108.         y = (*eqnFn)(x, coeff); /* calculate y */
  109.         if (fabs(classextended(y)) < 2)
  110.             skip = 2; /* y is a NAN */
  111.         else { /* get new Y screen coord */
  112.             lastvPos = vPos; /* save last Y coord */
  113.             vert = rint(170*(maxY-y)/(maxY-minY));
  114.             /* pin extreme values to window's edge */
  115.             if (vert+59>eqnDialog->portRect.bottom)
  116.                 vPos = eqnDialog->portRect.bottom-59;
  117.             else if (vert+59<eqnDialog->portRect.top)
  118.                 vPos = eqnDialog->portRect.top-59;
  119.             else vPos = vert;
  120.             if (y >= minY && y <= maxY) {
  121.                 /* y is in range */
  122.                 if (skip < 2) /* last y was not NAN */
  123.                     LineTo(170+hPos, 59+vPos);
  124.                 else MoveTo(170+hPos, 59+vPos);
  125.                 skip = 0;
  126.             } else { /* y is out of range */
  127.                 if (!skip) /* last point was in range */
  128.                     LineTo(170+hPos, 59+vPos);
  129.                 else MoveTo(170+hPos, 59+vPos);
  130.                 skip = 1;
  131.             }
  132.         }
  133.     } while ((hPos += 2) <= 300);
  134.     
  135.     SetRect(&bigRect, -32767, -32767, 32767, 32767);
  136.     ClipRect(&bigRect); /* reset clip rect */
  137. }
  138.  
  139. /* put up alert explaining the syntax error */
  140. void    SyntaxErr(int error)
  141. {
  142.     AlertTHndl    templateH;
  143.     Str255        str;
  144.     
  145.     InitCursor();
  146.     /* read alert into memory, make unpurgeable */
  147.     CouldAlert(301);
  148.     /* get handle to template */
  149.     templateH = (AlertTHndl) GetResource('ALRT', 301);
  150.     /* centre the alert box on the screen */
  151.     (*templateH)->boundsRect.left = (screenBits.bounds.right-screenBits.bounds.left - 260)/2;
  152.     (*templateH)->boundsRect.right = (*templateH)->boundsRect.left + 260;
  153.     GetIndString(str, 128, error); /* get message */
  154.     ParamText(str, "\p", "\p", "\p");
  155.     NoteAlert(301, NULL);
  156.     FreeAlert(301); /* mark alert purgeable again */
  157. }
  158.  
  159. /* get value from a dialog TE field */
  160. extended    GetEditField(int itemNo)
  161. {
  162.     Str255    str;
  163.     int        type;
  164.     extended    value;
  165.     Handle    edText;
  166.     Rect        rect;
  167.     
  168.     /* get handle to editable text */
  169.     GetDItem(eqnDialog, itemNo, &type, &edText, &rect);
  170.     GetIText(edText, str); /* retrieve text */
  171.     if (!str[0]) return 0; /* str is NULL */
  172.     value = str2num(str);
  173.     if (fabs(classextended(value)) < 2)
  174.         return 0; /* value is a NAN */
  175.     return value;
  176. }
  177.  
  178. pascal Boolean    DialogFilter(DialogPtr theDialog, EventRecord *theEvent, int *itemHit)
  179. {
  180.     Point        mousePt;
  181.     int        item, type;
  182.     char        c;
  183.     Rect        rect;
  184.     Handle    hand;
  185.     TEHandle    dialogTE;
  186.     
  187.     if (theEvent->what == keyDown) {
  188.         /* disable clear, enter keys in all fields */
  189.         c = theEvent->message & charCodeMask;
  190.         if (c == CLEAR_KEY || c == ENTER)
  191.             return true;
  192.         if (((DialogPeek) theDialog)->editField + 1 == FUNCTION) {
  193.             /* current edit field is function */
  194.             if (c == TAB) {
  195.                 /* override default tab behaviour */
  196.                 dialogTE = ((DialogPeek) theDialog)->textH;
  197.                 TEKey(TAB, dialogTE);
  198.                 return true;
  199.             }
  200.         } else if (c == RETURN)
  201.             /* disable return in other fields */
  202.             return true;
  203.     }
  204.     
  205.     /* set cursor as appropriate */
  206.     GetMouse(&mousePt);
  207.     item = 1 + FindDItem(theDialog, mousePt);
  208.     if (item) {
  209.         GetDItem(theDialog, item, &type, &hand, &rect);
  210.         if (type == editText) SetCursor(*iBeam);
  211.         else InitCursor();
  212.     } else InitCursor();
  213.  
  214.     return false;
  215. }
  216.  
  217. /* draw plot frame */
  218. pascal void    FramePlot(DialogPtr theDialog, short item)
  219. {
  220.     Rect        frameRect;
  221.     
  222.     SetRect(&frameRect, 168, 57, 472, 232);
  223.     FrameRect(&frameRect);
  224. }
  225.  
  226.